home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / File / Passwd / Authdigest.php < prev    next >
PHP Script  |  2004-10-01  |  11KB  |  353 lines

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: File :: Passwd :: Authdigest                                 |
  4. // +----------------------------------------------------------------------+
  5. // | This source file is subject to version 3.0 of the PHP license,       |
  6. // | that is available at http://www.php.net/license/3_0.txt              |
  7. // | If you did not receive a copy of the PHP license and are unable      |
  8. // | to obtain it through the world-wide-web, please send a note to       |
  9. // | license@php.net so we can mail you a copy immediately.               |
  10. // +----------------------------------------------------------------------+
  11. // | Copyright (c) 2003-2004 Michael Wallner <mike@iworks.at>             |
  12. // +----------------------------------------------------------------------+
  13. //
  14. // $Id: Authdigest.php,v 1.10 2004/06/07 19:19:47 mike Exp $
  15.  
  16. /**
  17. * Manipulate AuthDigestFiles as used for HTTP Digest Authentication.
  18. *
  19. * @author   Michael Wallner <mike@php.net>
  20. * @package  File_Passwd
  21. */
  22.  
  23. /**
  24. * Requires File::Passwd::Common
  25. */
  26. require_once 'File/Passwd/Common.php';
  27.  
  28. /**
  29. * Manipulate AuthDigestFiles as used for HTTP Digest Authentication.
  30. *
  31. * <kbd><u>
  32. *   Usage Example:
  33. * </u></kbd>
  34. * <code>
  35. *   $htd = &File_Passwd::factory('Authdigest');
  36. *   $htd->setFile('/www/mike/auth/.htdigest');
  37. *   $htd->load();
  38. *   $htd->addUser('mike', 'myRealm', 'secret');
  39. *   $htd->save();
  40. * </code>
  41. *
  42. * <kbd><u>
  43. *   Output of listUser()
  44. * </u></kbd>
  45. * <pre>
  46. *      array
  47. *       + user  => array
  48. *                   + realm => crypted_passwd
  49. *                   + realm => crypted_passwd
  50. *       + user  => array
  51. *                   + realm => crypted_passwd
  52. * </pre>
  53. * @author   Michael Wallner <mike@php.net>
  54. * @package  File_Passwd
  55. * @version  $Revision: 1.10 $
  56. * @access   public
  57. */
  58. class File_Passwd_Authdigest extends File_Passwd_Common
  59. {
  60.     /** 
  61.     * Path to AuthDigestFile
  62.     *
  63.     * @var string
  64.     * @access private
  65.     */
  66.     var $_file = '.htdigest';
  67.  
  68.     /** 
  69.     * Constructor
  70.     * 
  71.     * @access public
  72.     * @param string $file       path to AuthDigestFile
  73.     */
  74.     function File_Passwd_Authdigest($file = '.htdigest')
  75.     {
  76.         parent::__construct($file);
  77.     }
  78.  
  79.     /**
  80.     * Fast authentication of a certain user
  81.     * 
  82.     * Returns a PEAR_Error if:
  83.     *   o file doesn't exist
  84.     *   o file couldn't be opened in read mode
  85.     *   o file couldn't be locked exclusively
  86.     *   o file couldn't be unlocked (only if auth fails)
  87.     *   o file couldn't be closed (only if auth fails)
  88.     *
  89.     * @static   call this method statically for a reasonable fast authentication
  90.     * 
  91.     * @throws   PEAR_Error
  92.     * @access   public
  93.     * @return   mixed   true if authenticated, false if not or PEAR_Error
  94.     * @param    string  $file   path to passwd file
  95.     * @param    string  $user   user to authenticate
  96.     * @param    string  $pass   plaintext password
  97.     * @param    string  $realm  the realm the user is in
  98.     */
  99.     function staticAuth($file, $user, $pass, $realm)
  100.     {
  101.         $line = File_Passwd_Common::_auth($file, $user.':'.$realm);
  102.         if (!$line || PEAR::isError($line)) {
  103.             return $line;
  104.         }
  105.         @list(,,$real)= explode(':', $line);
  106.         return (md5("$user:$realm:$pass") === $real);
  107.     }
  108.     
  109.     /** 
  110.     * Apply changes and rewrite AuthDigestFile
  111.     *
  112.     * Returns a PEAR_Error if:
  113.     *   o directory in which the file should reside couldn't be created
  114.     *   o file couldn't be opened in write mode
  115.     *   o file couldn't be locked exclusively
  116.     *   o file couldn't be unlocked
  117.     *   o file couldn't be closed
  118.     * 
  119.     * @throws PEAR_Error
  120.     * @access public
  121.     * @return mixed true on success or a PEAR_Error
  122.     */
  123.     function save()
  124.     {
  125.         $content = '';
  126.         if (count($this->_users)) {
  127.             foreach ($this->_users as $user => $realm) {
  128.                 foreach ($realm as $r => $pass){
  129.                   $content .= "$user:$r:$pass\n";
  130.                 }
  131.             }
  132.         }
  133.         return $this->_save($content);
  134.     }
  135.  
  136.     /** 
  137.     * Add an user
  138.     *
  139.     * Returns a PEAR_Error if:
  140.     *   o the user already exists in the supplied realm
  141.     *   o the user or realm contain illegal characters
  142.     * 
  143.     * $user and $realm must start with an alphabetical charachter and must NOT
  144.     * contain any other characters than alphanumerics, the underline and dash.
  145.     * 
  146.     * @throws PEAR_Error
  147.     * @access public
  148.     * @return mixed true on success or a PEAR_Error
  149.     * @param string $user   the user to add
  150.     * @param string $realm  the realm the user should be in
  151.     * @param string $pass   the plaintext password
  152.     */
  153.     function addUser($user, $realm, $pass)
  154.     {
  155.         if ($this->userInRealm($user, $realm)) {
  156.             return PEAR::raiseError(
  157.                 "User '$user' already exists in realm '$realm'.", 0
  158.             );
  159.         }
  160.         if (!preg_match($this->_pcre, $user)) {
  161.             return PEAR::raiseError(
  162.                 sprintf(FILE_PASSWD_E_INVALID_CHARS_STR, 'User ', $user),
  163.                 FILE_PASSWD_E_INVALID_CHARS
  164.             );
  165.         }
  166.         if (!preg_match($this->_pcre, $realm)) {
  167.             return PEAR::raiseError(
  168.                 sprintf(FILE_PASSWD_E_INVALID_CHARS_STR, 'Realm ', $realm),
  169.                 FILE_PASSWD_E_INVALID_CHARS
  170.             );
  171.         }
  172.         $this->_users[$user][$realm] = md5("$user:$realm:$pass");
  173.         return true;
  174.     }
  175.  
  176.     /**
  177.     * List all user of (a | all) realm(s)
  178.     * 
  179.     * Returns:
  180.     *   o associative array of users of ONE realm if $inRealm was supplied
  181.     *     <pre>
  182.     *       realm1
  183.     *        + user1 => pass
  184.     *        + user2 => pass
  185.     *        + user3 => pass
  186.     *     </pre>
  187.     *   o associative array of all realms with all users
  188.     *     <pre>
  189.     *       array
  190.     *        + realm1 => array
  191.     *                     + user1 => pass
  192.     *                     + user2 => pass
  193.     *                     + user3 => pass
  194.     *        + realm2 => array
  195.     *                     + user3 => pass
  196.     *        + realm3 => array
  197.     *                     + user1 => pass
  198.     *                     + user2 => pass
  199.     *     </pre>
  200.     * 
  201.     * @access public
  202.     * @return array
  203.     * @param string $inRealm    the realm to list users of;
  204.     *                           if omitted, you'll get all realms
  205.     */
  206.     function listUserInRealm($inRealm = '')
  207.     {
  208.         $result = array();
  209.         foreach ($this->_users as $user => $realms){
  210.             foreach ($realms as $realm => $pass){
  211.                 if (!empty($inRealm) && ($inRealm !== $realm)) {
  212.                     continue;
  213.                 }
  214.                 if (!isset($result[$realm])) {
  215.                     $result[$realm] = array();
  216.                 }
  217.                 $result[$realm][$user] = $pass;
  218.             }
  219.         }
  220.         return $result;
  221.     }
  222.     
  223.     /** 
  224.     * Change the password of a certain user
  225.     *
  226.     * Returns a PEAR_Error if:
  227.     *   o user doesn't exist in the supplied realm
  228.     *   o user or realm contains illegal characters
  229.     * 
  230.     * This method in fact adds the user whith the new password
  231.     * after deleting the user.
  232.     * 
  233.     * @throws PEAR_Error
  234.     * @access public
  235.     * @return mixed true on success or a PEAR_Error
  236.     * @param string $user   the user whose password should be changed
  237.     * @param string $realm  the realm the user is in
  238.     * @param string $pass   the new plaintext password
  239.     */
  240.     function changePasswd($user, $realm, $pass)
  241.     {
  242.         if (PEAR::isError($error = $this->delUser($user, $realm))) {
  243.             return $error;
  244.         } else {
  245.             return $this->addUser($user, $realm, $pass);
  246.         }
  247.     }
  248.  
  249.     /** 
  250.     * Verifiy password
  251.     *
  252.     * Returns a PEAR_Error if the user doesn't exist in the supplied realm.
  253.     * 
  254.     * @throws PEAR_Error
  255.     * @access public
  256.     * @return mixed true if passwords equal, false if they don't, or PEAR_Error
  257.     * @param string $user   the user whose password should be verified
  258.     * @param string $realm  the realm the user is in
  259.     * @param string $pass   the plaintext password to verify
  260.     */
  261.     function verifyPasswd($user, $realm, $pass)
  262.     {
  263.         if (!$this->userInRealm($user, $realm)) {
  264.             return PEAR::raiseError(
  265.                 sprintf(FILE_PASSWD_E_USER_NOT_IN_REALM_STR, $user, $realm),
  266.                 FILE_PASSWD_E_USER_NOT_IN_REALM
  267.             );
  268.         }
  269.         return ($this->_users[$user][$realm] === md5("$user:$realm:$pass"));
  270.     }
  271.  
  272.     /**
  273.     * Ckeck if a certain user is in a specific realm
  274.     * 
  275.     * @throws PEAR_Error
  276.     * @access public
  277.     * @return boolean
  278.     * @param string $user   the user to check
  279.     * @param string $realm  the realm the user shuold be in
  280.     */
  281.     function userInRealm($user, $realm)
  282.     {
  283.       return (isset($this->_users[$user][$realm]));
  284.     }
  285.     
  286.     /**
  287.     * Delete a certain user in a specific realm
  288.     *
  289.     * Returns a PEAR_Error if <var>$user</var> doesn't exist <var>$inRealm</var>.
  290.     * 
  291.     * @throws PEAR_Error
  292.     * @access public
  293.     * @return mixed true on success or PEAR_Error
  294.     * @param  string    $user       the user to remove
  295.     * @param  string    $inRealm    the realm the user should be in
  296.     */
  297.     function delUserInRealm($user, $inRealm)
  298.     {
  299.         if (!$this->userInRealm($user, $inRealm)) {
  300.             return PEAR::raiseError(
  301.                 sprintf(FILE_PASSWD_E_USER_NOT_IN_REALM_STR, $user, $inRealm),
  302.                 FILE_PASSWD_E_USER_NOT_IN_REALM
  303.             );
  304.         }
  305.         unset($this->_users[$user][$inRealm]);
  306.         return true;
  307.     }
  308.     
  309.     /** 
  310.     * Parse the AuthDigestFile
  311.     *
  312.     * Returns a PEAR_Error if AuthDigestFile has invalid format.
  313.     * 
  314.     * @throws PEAR_Error
  315.     * @access public
  316.     * @return mixed true on success or PEAR_Error
  317.     */
  318.     function parse()
  319.     {
  320.         $this->_users = array();
  321.         foreach ($this->_contents as $line) {
  322.             $user = explode(':', $line);
  323.             if (count($user) != 3) {
  324.                 return PEAR::raiseError(
  325.                     FILE_PASSWD_E_INVALID_FORMAT_STR,
  326.                     FILE_PASSWD_E_INVALID_FORMAT
  327.                 );
  328.             }
  329.             list($user, $realm, $pass) = $user;
  330.             $this->_users[$user][$realm] = trim($pass);
  331.         }
  332.         $this->_contents = array();
  333.         return true;
  334.     }
  335.     
  336.     /**
  337.     * Generate Password
  338.     *
  339.     * @static
  340.     * @access   public
  341.     * @return   string  The crypted password.
  342.     * @param    string  $user The username.
  343.     * @param    string  $realm The realm the user is in.
  344.     * @param    string  $pass The plaintext password.
  345.     */
  346.     function generatePassword($user, $realm, $pass)
  347.     {
  348.         return md5("$user:$realm:$pass");
  349.     }
  350.     
  351. }
  352. ?>